#ifndef __M_LOOP_H__
#define __M_LOOP_H__

// 包含必要的头文件
#include "util.hpp"
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include "buffer.hpp"

namespace bitlog {

    /// @brief 异步循环器类，用于管理异步任务的执行
    class AsyncLooper {
        public:
            // 定义了一个函数类型 Functor，该类型接收一个 Buffer 引用作为参数
            using Functor = std::function<void(Buffer &buffer)>;
            // 智能指针类型定义，便于管理 AsyncLooper 对象的生命周期
            using ptr = std::shared_ptr<AsyncLooper>;

            /// @brief 构造函数，初始化异步循环器
            /// @param cb 用于处理任务的回调函数
            AsyncLooper(const Functor &cb)
                : _running(true),            // 标志位 _running 初始化为 true，表示循环器正在运行
                  _looper_callback(cb),      // 初始化回调函数
                  _thread(std::thread(&AsyncLooper::worker_loop, this)) {  // 启动一个新线程，执行 worker_loop 方法
            }

            /// @brief 析构函数，停止循环器
            ~AsyncLooper() { stop(); }

            /// @brief 停止异步循环器
            void stop() { 
                _running = false;             // 将运行标志位设为 false，通知线程停止
                _pop_cond.notify_all();       // 通知所有等待在 _pop_cond 上的线程
                _thread.join();               // 等待工作线程结束
            }

            /// @brief 向循环器推送任务
            /// @param msg 要处理的消息
            void push(const std::string &msg) {
                if (_running == false) return;  // 如果循环器已经停止，不再接收任务
                {
                    std::unique_lock<std::mutex> lock(_mutex);  // 加锁，保护共享数据
                    // 等待直到任务缓冲区有足够的空间写入新的消息
                    _push_cond.wait(lock, [&]{ return _tasks_push.writeAbleSize() >= msg.size(); });
                    _tasks_push.push(msg.c_str(), msg.size());  // 将消息推入任务缓冲区
                }
                _pop_cond.notify_all();  // 通知等待在 _pop_cond 上的线程，有新任务到来
            }

        private:
            /// @brief 工作线程的主循环，用于处理任务
            void worker_loop() {
                while (1) {
                    {
                        std::unique_lock<std::mutex> lock(_mutex);  // 加锁，保护共享数据
                        // 如果循环器已经停止且没有剩余任务，退出循环
                        if (_running == false && _tasks_push.empty()) { return; }
                        // 等待直到任务缓冲区中有任务或者循环器停止
                        _pop_cond.wait(lock, [&]{ return !_tasks_push.empty() || !_running; });
                        _tasks_push.swap(_tasks_pop);  // 交换任务缓冲区，准备处理任务
                    }
                    _push_cond.notify_all();  // 通知等待在 _push_cond 上的线程，缓冲区有空间了
                    _looper_callback(_tasks_pop);  // 调用回调函数处理任务
                    _tasks_pop.reset();  // 重置任务缓冲区，准备接收新任务
                }
                return;
            }

        private:
            Functor _looper_callback;  // 回调函数，用于处理任务
            std::mutex _mutex;  // 互斥锁，保护共享数据的访问
            std::atomic<bool> _running;  // 原子布尔值，表示循环器是否正在运行
            std::condition_variable _push_cond;  // 条件变量，用于控制任务推送操作
            std::condition_variable _pop_cond;  // 条件变量，用于控制任务处理操作
            Buffer _tasks_push;  // 任务推送缓冲区
            Buffer _tasks_pop;  // 任务处理缓冲区
            std::thread _thread;  // 工作线程，用于异步处理任务
    };
}

#endif